use std::{env, fs};
use pest_derive::Parser;
use pest::Parser;
use pest::iterators::Pairs;
use pest::error::LineColLocation;

// use std::fs::OpenOptions;
// use std::io::Write;

#[derive(Parser)]
#[grammar = "lexer.pest"]
struct SysYParser;

fn main() {
    // 收集命令行参数
    let args: Vec<String> = env::args().collect();

    // 检查是否提供了文件名
    if args.len() < 2 {
        eprintln!("Usage: {} <filename>", args[0]);
        std::process::exit(1);
    }

    // 获取文件名
    let filename = &args[1];

    // 读取输入文件
    let input = fs::read_to_string(filename).expect("Failed to read file");

    // let mut file = OpenOptions::new()
    //     .create(true)    // 如果文件不存在则创建
    //     .append(true)    // 追加模式
    //     .open("app.log").expect("Failed to open file");

    // let _ = file.write_all(input.clone().as_bytes());

    let parse_result = SysYParser::parse(Rule::TOKENIZATION, &input);

    match parse_result {
        Ok(pairs) => {
            let mut correct_tokens = Vec::new();
            let mut error_tokens = Vec::new();
            // 成功解析，处理 Pairs
            collect_inner_rules(pairs, & mut correct_tokens, & mut error_tokens);
            if error_tokens.len() > 0 {
                for t in error_tokens {
                    eprintln!("{}", t.to_string());
                }
            } else {
                for t in correct_tokens {
                    eprintln!("{}", t.to_string());
                }
            }
        }
        Err(error) => {
            // 处理语法错误
            let line_col = match error.line_col {
                LineColLocation::Pos(line_col) => line_col,
                LineColLocation::Span(start_line_col, _) => start_line_col,
            };
            eprintln!("Error type A at Line {}: Mysterious character \"{}\".", line_col.0, error.line().chars().nth(line_col.1 - 1).unwrap());
        }
    }
}

// 首先定义 PrintToken 结构体，需要指定生命周期
#[derive(Debug)]
struct PrintToken {
    rule: Rule,
    text: String,  // 改为 String 类型以避免生命周期问题
    line: usize,
}

impl PrintToken {
    pub fn to_string(&self) -> String {
        match self.rule {
            Rule::ERROR_TOKEN => {
                format!(
                    "Error type A at Line {}: Mysterious character \"{}\".",
                    self.line, self.text
                )
            },
            _ => {
                format!(
                    "{:?} {} at Line {}.",
                    self.rule, self.text, self.line
                )
            }
        }
    }
}

fn collect_inner_rules(
    pairs: Pairs<Rule>, 
    correct_tokens: &mut Vec<PrintToken>, 
    error_tokens: &mut Vec<PrintToken>
) {
    for pair in pairs {
        let rule = pair.as_rule();
        let text = pair.as_str().to_string(); // 转换为 String
        let line = pair.as_span().start_pos().line_col().0;

        // 检查是否有子规则
        let inner_pairs = pair.into_inner();
        if inner_pairs.clone().count() == 0 {
            // 如果没有子规则，打印内容（最内层）
            match rule {
                Rule::DECIMAL => {
                    correct_tokens.push(PrintToken {
                        rule: Rule::INTEGER_CONST, 
                        text, 
                        line
                    });
                }, 
                Rule::OCTAL => {
                    let trimmed = text.trim_start_matches("0");
                    let decimal_num = i32::from_str_radix(trimmed, 8)
                        .expect("Invalid octal number");
                    correct_tokens.push(PrintToken {
                        rule: Rule::INTEGER_CONST, 
                        text: decimal_num.to_string(), 
                        line
                    });
                },
                Rule::HEXADECIMAL => {
                    let trimmed = text.trim_start_matches("0x")
                        .trim_start_matches("0X");
                    let decimal_num = i32::from_str_radix(trimmed, 16)
                        .expect("Invalid hex number");
                    correct_tokens.push(PrintToken {
                        rule: Rule::INTEGER_CONST, 
                        text: decimal_num.to_string(), 
                        line
                    });
                },
                Rule::ERROR_TOKEN => {
                    error_tokens.push(PrintToken {rule, text, line});
                }
                Rule::EOI => { /*do nothing*/ },
                _ => {
                    correct_tokens.push(PrintToken {rule, text, line});
                },
            }
        } else {
            // 递归处理子规则
            collect_inner_rules(inner_pairs, correct_tokens, error_tokens);
        }
    }
}

// #[derive(Parser)]
// #[grammar = "lexer.pest"]  // 指向你的 .pest 文件
// struct SysYtParser;

// #[derive(Debug, PartialEq)]
// pub enum Token {
//     Integer(i64),
//     Operator(char),
// }
// pub fn tokenize(input: &str) -> Vec<Token> {
//     let pair = SysYtParser::parse(Rule::expr, input)
//         .unwrap_or_else(|e| panic!("Parse error: {}", e))
//         .next()
//         .unwrap(); // 取第一个匹配
//     pair.into_inner()
//         .map(|p| match p.as_rule() {
//             Rule::int => Token::Integer(p.as_str().parse().unwrap()),
//             Rule::op => Token::Operator(p.as_str().chars().next().unwrap()),
//             _ => unreachable!(),
//         })
//         .collect()
// }